#ifndef PACKET_HPP
#define PACKET_HPP

#include <boost/scoped_array.hpp>
#include <boost/cstdint.hpp>

namespace kieper {
    class Packet {
    public:
        /**
         * Size of the message header, in bytes
         */
        static const unsigned int HEADER_SIZE = 8;
        
        enum Type {
            TYPE_CONTROL = 0,
            TYPE_DATA = 1 
        };

        enum Delivery {
            DELIVERY_SYNC = 0,
            DELIVERY_ASYNC = 1
        };

        enum Scope {
            SCOPE_GLOBAL = 0,
            SCOPE_DEVICE_SPECIFIC = 1
        };

        enum Direction {
            DIRECTION_REQUEST = 0,
            DIRECTION_RESPONSE = 1
        };

        Packet(unsigned int payloadSize);
        Packet(unsigned int payloadSize, Type type, Delivery delivery, Scope scope,
                Direction direction, uint16_t messageNumber);
        Packet(unsigned int payloadSize, const char* buffer);
        ~Packet();

        const char* getBuffer() const;
        char* getPayload() const;
        unsigned int getTotalSize() const;

        void setPacketId(uint32_t packetId);
        void setDeviceId(uint16_t deviceId);

        void setMessageInfo(Packet::Type type, Packet::Delivery delivery,
            Packet::Scope scope, Packet::Direction direction, uint16_t messageNumber);
        
        void setMessageNumber(uint16_t number);
        
        uint32_t getPacketId(); 
        uint16_t getDeviceId();
        
        Packet::Type getType();
        Packet::Delivery getDelivery();
        Packet::Scope getScope();
        Packet::Direction getDirection();

        uint16_t getMessageNumber();

    protected:
    private:
        unsigned int payloadSize_;
        boost::scoped_array<char> buffer_;

        Packet(const Packet& other);
        Packet& operator=(const Packet& other);
    };
}

#endif
